package com.wyw.hemerocallis.filter;

import com.wyw.hemerocallis.constant.CommonConstant;
import com.wyw.hemerocallis.util.TokenParseUtil;
import com.wyw.hemerocallis.vo.LoginUserInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 用户统一的身份登录拦截
 *
 * @author Mr Wu    yewen.wu.china@gmail.com
 * <p>
 * Update History:
 * Author        Time            Content
 */
@SuppressWarnings("all")
@Slf4j
@Component
public class LoginUserInfoInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response,
                             Object handler) throws Exception {
        // 部分请求不需要带有身份信息, 即白名单
        if (checkWhiteListUrl(request.getRequestURI())) {
            return true;
        }

        //先尝试从http header中拿到token
        String token = request.getHeader(CommonConstant.JWT_USER_INFO_KEY);
        LoginUserInfo loginUserInfo = null;

        try {
            loginUserInfo = TokenParseUtil.parseUserInfoFromToken(token);
        } catch (Exception ex) {
            log.error("loginInfo 转换异常:{}", ex.getMessage(), ex);
        }

        //程序一般不会走这里，除非不使用gateway做网关
        if (null == loginUserInfo) {
            throw new RuntimeException("can not parse current login user");
        }
        log.info("设置登录用户信息:{}", request.getRequestURI());
        //设置当前请求上下文，把用户信息放进去
        AccessContext.setLoginUserInfo(loginUserInfo);

        return true;
    }

    /**
     * 一般对返回结果进行修改，才使用此处
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    /**
     * 请求完全结束后调用，常用于清理资源等工作
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        if (null != AccessContext.getLoginInfo()) {
            AccessContext.clearLoginUserInfo();
        }
    }

    /**
     * 白名单
     * @param url
     * @return
     */
    private boolean checkWhiteListUrl(String url) {
        return StringUtils.containsAny(
                url,
                "springfox", "swagger", "v2",
                "webjars", "doc.html"
        );
    }
}
